package com.book.lizhi.read;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap;
import java.util.Vector;

import android.graphics.Paint;
import android.text.TextUtils;

import com.book.lizhi.util.FileUtil;
import com.book.lizhi.util.Util;

public class ReadFactory {
	private MappedByteBuffer mBuffer;
	private RandomAccessFile mRAFile;
	private int mWidth;
	private int mHeight;
	private int mLineHeight;
	private int mLine;
	public Paint mPaint;

	public int curPosition = 0;
	public int prePosition = 0;
	public int fileLen = 0;

	public boolean isFinish = false;
	public String mCurCid;

	private HashMap<String, Integer> mLastPosition;

	public ReadFactory(int width, int height, int lineHeight, Paint paint) {
		mWidth = width;
		mHeight = height;
		mLineHeight = lineHeight;
		mPaint = paint;

		mLine = mHeight / mLineHeight;

		mLastPosition = new HashMap<String, Integer>();
	}

	public void initFactory(String path) {
		try {
			mRAFile = new RandomAccessFile(path, "r");
			fileLen = (int) mRAFile.length();
			mBuffer = mRAFile.getChannel().map(MapMode.READ_ONLY, 0, fileLen);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public boolean initChapter(String bid, String cid) {
		mCurCid = cid;
		if (mRAFile != null) {
			try {
				mRAFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		curPosition = 0;
		prePosition = 0;
		File floder = new File(FileUtil.getCacheFile().getAbsoluteFile() + File.separator + bid);
		if (floder.exists()) {
			File cidFile = new File(floder, cid);
			if (cidFile.exists()) {
				return initFactory(cidFile);
			}
		}
		return false;
	}

	public boolean initPreChapter(String bid, String cid) {
		mCurCid = cid;
		if (mRAFile != null) {
			try {
				mRAFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		File floder = new File(FileUtil.getCacheFile().getAbsoluteFile() + File.separator + bid);
		if (floder.exists()) {
			File cidFile = new File(floder, cid);
			if (cidFile.exists()) {
				boolean resut = initFactory(cidFile);
				prePosition = curPosition = fileLen;
				return resut;
			}
		}
		return false;
	}

	public boolean resetChapter(boolean isNeedFixPosition, String bid, String cid, int position) {
		mCurCid = cid;
		boolean result = initChapter(bid, cid);
		if (isNeedFixPosition) {
			if (position > curPosition) {
				position = readNextPosition(position);
			} else {
				position = readPrePosition(position - 1, position);
			}
		}
		prePosition = curPosition = position;
		return result;
	}

	public boolean resetChapter(Paint paint, int line) {
		mPaint = paint;
		curPosition = prePosition;
		mLine = line;
		return true;
	}

	public void restPaint(Paint paint) {
		mPaint = paint;
	}

	private boolean initFactory(File cidFile) {
		try {

			mRAFile = new RandomAccessFile(cidFile, "r");
			fileLen = (int) mRAFile.length();
			if (fileLen <= 0) {
				return false;
			}
			mBuffer = mRAFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileLen);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	public Vector<String> prePage() {
		if (mLastPosition.containsKey(mCurCid) && prePosition == mLastPosition.get(mCurCid)) {
			mLastPosition.remove(mCurCid);
		}

		if (prePosition != 0) {
			curPosition = prePosition;
		}

		if (prePosition < 0)
			prePosition = 0;
		Vector<String> lines = new Vector<String>();
		String strParagraph = "";
		while (lines.size() < mLine && prePosition > 0) {
			Vector<String> paraLines = new Vector<String>();
			byte[] paraBuf = readPreParagraph(prePosition);
			prePosition -= paraBuf.length;
			try {
				strParagraph = new String(paraBuf, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			// strParagraph = strParagraph.replaceAll("\r\n", "");
			// strParagraph = strParagraph.replaceAll("\n", "");

			if (strParagraph.length() == 0) {
				paraLines.add(strParagraph);
			}
			while (strParagraph.length() > 0) {
				int nSize = mPaint.breakText(strParagraph, true, mWidth, null);
				paraLines.add(strParagraph.substring(0, nSize));
				strParagraph = strParagraph.substring(nSize);
			}
			lines.addAll(0, paraLines);
		}
		while (lines.size() > mLine) {
			try {
				prePosition += lines.get(0).getBytes("UTF-8").length;
				lines.remove(0);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}

		int tempPosition = prePosition;

		if (mLastPosition.containsKey(mCurCid)) {
			while (prePosition < mLastPosition.get(mCurCid)) {
				try {
					if (lines.size() == 0) {
						mLastPosition.put(mCurCid, tempPosition);
						break;
					}
					prePosition += lines.get(0).getBytes("UTF-8").length;
					lines.remove(0);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
			prePosition = mLastPosition.get(mCurCid);
			// mLastPosition.remove(mCurCid);
		}

		return lines;
	}

	private byte[] readPreParagraph(int position) {

		int i = position - 1;
		i = readPrePosition(i, position);

		if (i < 0)
			i = 0;
		int nParaSize = position - i;
		int j;
		byte[] buf = new byte[nParaSize];
		for (j = 0; j < nParaSize; j++) {
			buf[j] = mBuffer.get(i + j);
			buf[j] = Util.encryptMethod(buf[j]);
		}
		return buf;
	}

	private int readPrePosition(int i, int position) {
		while (i > 0) {
			byte b0 = mBuffer.get(i);
			b0 = Util.encryptMethod(b0);
			if (b0 == 0x0a && i != position - 1) {
				i++;
				break;
			}
			i--;
		}
		return i;
	}

	public Vector<String> nextPage() {
		prePosition = curPosition;
		Vector<String> vector = new Vector<String>(mLine);

		String content = readNextParagraph(curPosition);
		if (TextUtils.isEmpty(content)) {
			return vector;
		}
		for (int i = 0; i < mLine; i++) {
			int size = mPaint.breakText(content, true, mWidth, null);
			String temp = content.substring(0, size);
			vector.add(temp);
			curPosition += temp.getBytes().length;
			content = content.substring(size, content.length());
			if (TextUtils.isEmpty(content)) {
				content = readNextParagraph(curPosition);
				if (TextUtils.isEmpty(content)) {
					break;
				}
			}
		}

		if (!TextUtils.isEmpty(content)) {
			mLastPosition.remove(mCurCid);
		}

		return vector;
	}

	private String readNextParagraph(int position) {
		int nStart = position;
		int i = nStart;

		i = readNextPosition(i);

		if (i >= fileLen) {
			isFinish = true;
			if (!mLastPosition.containsKey(mCurCid) && prePosition != fileLen) {
				mLastPosition.put(mCurCid, prePosition);
			}
		}
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++) {
			buf[i] = mBuffer.get(position + i);
			buf[i] = Util.encryptMethod(buf[i]);
		}
		return new String(buf);
	}

	private int readNextPosition(int i) {
		while (i < fileLen) {
			byte b0 = mBuffer.get(i++);
			b0 = Util.encryptMethod(b0);
			if (b0 == 0x0a) {
				break;
			}
		}
		return i;
	}
}
